﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CarShop.Domain.Entities;
using CarShop.Domain.Interfaces;
using CarShop.Domain.Interfaces.Repositories;
using CarShop.Services.Contracts.Interfaces;

namespace CarShop.Services
{
    public class OrderService : ServiceBase, IOrderService
    {
        private IOrderRepository _orderRepository;
        private IOrderStatusRepository _orderStatusRepository;
        private ICarStatusRepository _carStatusRepository;
        private ICarRepository _carRepository;

        public OrderService(IUnitOfWork unitOfWork, 
            IOrderRepository orderRepository, 
            IOrderStatusRepository orderStatusRepository, 
            ICarStatusRepository carStatusRepository,
            ICarRepository carRepository) :base(unitOfWork)
        {
            _orderStatusRepository = orderStatusRepository;
            _orderRepository = orderRepository;
            _carStatusRepository = carStatusRepository;
            _carRepository = carRepository;
        }

        public IEnumerable<Order> GetOrders(Func<Order, bool> predicate, int page, int countOnPage, out int totalPages)
        {
            IEnumerable<Order> result = _orderRepository.GetPaged(predicate, page, countOnPage, out totalPages,
                c => c.CreationDate, false, null);

            return result;
        }

        public bool AddOrder(Order order)
        {
            bool result = false;

            try
            {
                _orderRepository.Add(order);
                _unitOfWork.Commit();

                result = true;
            }
            catch
            {

            }

            return result;
        }

        public bool UpdateOrder(Order order)
        {
            bool result = false;

            try
            {
                _orderRepository.Update(order);
                _unitOfWork.Commit();

                result = true;
            }
            catch
            {

            }

            return result;
        }

        public bool CompleteOrder(Order order)
        {
            bool result = false;

            try
            {
                int completeOrderStatusId =
                _orderStatusRepository.GetAll()
                .Where(o => o.Name == OrderStatus.NameFor.Completed)
                .Select(o => o.Id)
                .SingleOrDefault();

                int soldCarStatusId =
                    _carStatusRepository.GetAll()
                        .Where(o => o.Name == CarStatus.NameFor.Sold)
                        .Select(o => o.Id)
                        .SingleOrDefault();

                order.OrderStatusId = completeOrderStatusId;
                _orderRepository.Update(order);

                IEnumerable<Car> orderCars = _carRepository.GetAll().Where(c => c.OrderId == order.Id);

                foreach (var car in orderCars)
                {
                    car.CarStatusId = soldCarStatusId;
                    _carRepository.Update(car);
                }

                _unitOfWork.Commit();

                result = true;
            }
            catch
            {
            }

            return result;
        }

        public bool CancelOrder(Order order)
        {
            bool result = false;

            try
            {
                int cancelOrderStatusId =
                _orderStatusRepository.GetAll()
                .Where(o => o.Name == OrderStatus.NameFor.Cancelled)
                .Select(o => o.Id)
                .SingleOrDefault();

                order.OrderStatusId = cancelOrderStatusId;
                _orderRepository.Update(order);

                IEnumerable<Car> orderCars = _carRepository.GetAll().Where(c => c.OrderId == order.Id);

                foreach (var car in orderCars)
                {
                    car.OrderId = null;
                    _carRepository.Update(car);
                }

                _unitOfWork.Commit();

                result = true;
            }
            catch
            {
            }

            return result;
        }



        public Order GetOrder(int id)
        {
            Order result = _orderRepository.Get(id);
            return result;
        }

        public Order GetOrderWithAllInfo(int id)
        {
            Order result = _orderRepository.GetAll("Cars", "OrderStatus", "User")
                .SingleOrDefault(c => c.Id == id);

            return result;
        }

    }
}
